package com.ysw.spring.spring_util.json;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
 * Json工具类
 * @author zhangyongqi
 * @since 1.0
 */
public final class JsonUtils {

    private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class);
    private static final ObjectMapper MAPPER;

    static {
        MAPPER = new ObjectMapper();
        MAPPER.registerModule(new Jdk8Module());
        MAPPER.registerModule(new JavaTimeModule());
        MAPPER.registerModule(new GuavaModule());
        MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        MAPPER.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
    }

    private JsonUtils() {
    }

    @Setter
    @Getter
    @ToString
    public static class Model {
        private String key1;
        private String key2;
        private String key3;
        private String key4;
    }

    /**
     * 将空字符串""或空数组"[]"转换成空对象"{}"格式
     */
    public static String toEmptyJsonObject(String json) {
        if (StringUtils.isBlank(json) || "[]".equals(json.trim())) {
            return "{}";
        }
        return json;
    }

    /**
     * 将json解析为指定类型，会屏蔽异常
     */
    public static <T> T stringToObject(String jsonString, Class<T> cla) {
        if (StringUtils.isBlank(jsonString)) {
            return null;
        }
        try {
            return MAPPER.readValue(jsonString, cla);
        } catch (IOException e) {
            logger.error(String.format("convert json string to obj error, json:%s", jsonString), e);
            return null;
        }
    }

    /**
     * 将json解析为指定类型，会屏蔽异常
     */
    public static <T> T stringToObject(String jsonString, TypeReference<T> typeReference) {
        if (StringUtils.isBlank(jsonString)) {
            return null;
        }
        try {
            return MAPPER.readValue(jsonString, typeReference);
        } catch (IOException e) {
            logger.error(String.format("convert json string to obj error, json:%s", jsonString), e);
            return null;
        }
    }

    /**
     * 将对象序列化为字符串，会屏蔽异常
     */
    public static String objectToString(Object object) {
        if (object == null) {
            return null;
        }
        try {
            return MAPPER.writer().writeValueAsString(object);
        } catch (IOException e) {
            logger.error(String.format("convert obj to json string error, obj:%s", object), e);
            return null;
        }
    }

    /**
     * 将json转换为指定的对象，该方法将异常抛出交由上层处理
     */
    public static <T> T stringToObject2(String jsonString, Class<T> cla) {
        if (StringUtils.isBlank(jsonString)) {
            return null;
        }
        try {
            return MAPPER.readValue(jsonString, cla);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将json转换为指定的类型，该方法将异常抛出交由上层处理
     */
    public static <T> T stringToObject2(String jsonString, TypeReference<T> typeReference) {
        if (StringUtils.isBlank(jsonString)) {
            return null;
        }
        try {
            return MAPPER.readValue(jsonString, typeReference);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将对象转换为json，该方法将异常抛出交由上层处理
     */
    public static String objectToString2(Object object) {
        if (object == null) {
            return null;
        }
        try {
            return MAPPER.writer().writeValueAsString(object);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 判断是否为json字符串
     */
    public static boolean isValidJson(String json) {
        if(!json.startsWith("{")){
            return false;
        }
        try {
            MAPPER.readTree(json);
            return true;
        } catch (JsonProcessingException e) {
            return false;
        } catch (IOException e) {
            return false;
        }
    }


    public static ObjectMapper mapper() {
        return MAPPER;
    }

    public static ObjectReader reader() {
        return MAPPER.reader();
    }
}
